package com.gsdl.model.bo;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NoResultException;

import org.apache.log4j.Logger;

import com.gsdl.model.entity.Centro;
import com.gsdl.model.entity.Deposito;
import com.gsdl.model.entity.Material;
import com.gsdl.model.entity.MaterialPedido;
import com.gsdl.model.entity.Movimento;
import com.gsdl.model.entity.Movimento.TipoMovimento;
import com.gsdl.model.entity.Pedido;
import com.gsdl.model.entity.Movimento;
import com.gsdl.model.entity.Stock;
import com.gsdl.model.entity.TipoPedido;
import com.gsdl.model.entity.Pedido.EstadoPedido;

// TODO: Auto-generated Javadoc
/**
 * The Class PedidoBO.
 */
public class PedidoBO extends BaseBO<Pedido> {

	/** The Constant LOG. */
	private static final Logger LOG = Logger.getLogger(PedidoBO.class.getName());
	
	/** The instance. */
	private static PedidoBO instance = new PedidoBO();
	
	/**
	 * Gets the single instance of PedidoBO.
	 *
	 * @return single instance of PedidoBO
	 */
	public static PedidoBO getInstance() {
		return instance;
	}
	
	/**
	 * Instantiates a new pedido bo.
	 */
	private PedidoBO() {
		super(new Pedido());
		
	}
	
	/**
	 * Gets the tipos pedido.
	 *
	 * @return the tipos pedido
	 */
	public List<TipoPedido> getTiposPedido(){
		return (List<TipoPedido>)getAll(TipoPedido.class);
	}
	
	/**
	 * Save movimento.
	 *
	 * @param movimento the movimento
	 * @return the movimento
	 */
	public Movimento saveMovimento(Movimento movimento) {
		movimento = saveEntity(movimento);
		return movimento;
	}
	
	/**
	 * Gets the pedidos by centro.
	 *
	 * @param centro the centro
	 * @return the pedidos by centro
	 */
	@SuppressWarnings("unchecked")
	public List<Pedido> getPedidosByCentro(Centro centro) {
		EntityManager em = null;
        try {
            em = getEntityManager();
          
			List<Pedido> pedidos = (List<Pedido>)  em.createNamedQuery("Pedido.findByCentro")
            		.setParameter("centroId", centro.getId())
            		.getResultList();
            return pedidos;
            
        } catch (NoResultException ex) {
            LOG.warn(ex.getMessage());
        }catch (Exception ex) {
        	LOG.warn(ex.getMessage());
        }finally{
        	
        	closeSession(em);
        }
        
		return new ArrayList<Pedido>();
	}
	
	/**
	 * Gets the pedidos by estado.
	 *
	 * @param estadoPedido the estado pedido
	 * @return the pedidos by estado
	 */
	@SuppressWarnings("unchecked")
	public List<Pedido> getPedidosByEstado(EstadoPedido estadoPedido) {
		EntityManager em = null;
        try {
            em = getEntityManager();
          
			List<Pedido> pedidos = (List<Pedido>)  em.createNamedQuery("Pedido.findByEstado")
            		.setParameter("estado", estadoPedido)
            		.getResultList();
            return pedidos;
            
        } catch (NoResultException ex) {
            LOG.warn(ex.getMessage());
        }catch (Exception ex) {
        	LOG.warn(ex.getMessage());
        }finally{
        	
        	closeSession(em);
        }
        
		return new ArrayList<Pedido>();
	}
	
	/**
	 * Gets the pedidos by centro and estado.
	 *
	 * @param centro the centro
	 * @param estadoPedido the estado pedido
	 * @return the pedidos by centro and estado
	 */
	@SuppressWarnings("unchecked")
	public List<Pedido> getPedidosByCentroAndEstado(Centro centro, EstadoPedido estadoPedido) {
		EntityManager em = null;
        try {
            em = getEntityManager();
          
			List<Pedido> pedidos = (List<Pedido>)  em.createNamedQuery("Pedido.findByCentroAndEstado")
            		.setParameter("centroId", centro.getId())
            		.setParameter("estado", estadoPedido)
            		.getResultList();
            return pedidos;
            
        } catch (NoResultException ex) {
            LOG.warn(ex.getMessage());
        }catch (Exception ex) {
        	LOG.warn(ex.getMessage());
        }finally{
        	
        	closeSession(em);
        }
        
		return new ArrayList<Pedido>();
	}
	
	/**
	 * Save expedicao.
	 *
	 * @param pedido the pedido
	 * @return the pedido
	 */
	public Pedido saveExpedicao(Pedido pedido){
		pedido.setEstadoPedido(EstadoPedido.EXPEDIDO);
		pedido.setDataExpedicao(new Date());
		save(pedido);

		return pedido;
	}
	
	
	/**
	 * Save pedido.
	 *
	 * @param pedido the pedido
	 * @param movimentos the movimentos
	 * @return the pedido
	 */
	public Pedido savePedido(Pedido pedido, List<Movimento> movimentos){
		return savePedido(pedido, movimentos, TipoMovimento.SAIDA);
	}
	
	/**
	 * Save pedido, inserts a movimento record for each material in the pedido, and updates the stock
	 *
	 * @param pedido the pedido
	 * @param movimentos the movimentos
	 * @param tipoMovimento the tipo movimento
	 * @return the pedido
	 */
	public Pedido savePedido(Pedido pedido, List<Movimento> movimentos, TipoMovimento tipoMovimento){
		
		pedido = save(pedido);
		
		Date dataPedido = pedido.getDataPedido();
		Date dataMovimento = new Date();
        for(Movimento movimento: movimentos){
        	if(tipoMovimento.equals(TipoMovimento.REPOSICAO)){
        		Movimento mov = new Movimento();
        		mov.setPedido(pedido);
        		mov.setMaterial(movimento.getMaterial());
        		mov.setDeposito(movimento.getDeposito());
        		mov.setTipoMovimento(tipoMovimento);
        		mov.setDataMovimento(dataMovimento);
        		mov.setQuantidade(movimento.getQuantidade());
        		mov = MovimentoBO.getInstance().saveMovimentoAndUpdateStock(mov);
        		
        	}else{
        		movimento.setPedido(pedido);
        		movimento.setTipoMovimento(tipoMovimento);
        		movimento.setDataMovimento(dataPedido);
        		movimento = MovimentoBO.getInstance().saveMovimentoAndUpdateStock(movimento);
        	}
        	
        }
		
		return pedido;
	}

}
